<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>行商浪人对话图片生成器</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: Arial, sans-serif;
            background-color: #101811;
            color: white;
            padding: 20px;
            min-height: 100vh;
        }

        .container {
            display: flex;
            gap: 20px;
            max-width: 1800px;
            margin: 0 auto;
            align-items: flex-start;
        }

        .preview-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        .preview-area {
            width: 100%;
            max-width: 1300px;
            background-color: #1a1a1a;
            border-radius: 8px;
            padding: 15px;
            margin-bottom: 20px;
        }

        .canvas-container {
            width: 100%;
            height: 731px; /* 1300 * 9/16 = 731.25 取整 */
            position: relative;
            overflow: hidden;
            background-color: #2a2a2a;
            border-radius: 4px;
        }

        #previewCanvas {
            width: 100%;
            height: 100%;
            object-fit: contain;
        }

        .preview-controls {
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 20px;
            margin-bottom: 20px;
            width: 100%;
        }

        .nav-btn {
            background-color: #146C1D;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.2s;
        }

        .nav-btn:hover:not(:disabled) {
            background-color: #1a8a25;
        }

        .nav-btn:disabled {
            background-color: #555;
            cursor: not-allowed;
        }

        .page-indicator {
            font-size: 18px;
            min-width: 100px;
            text-align: center;
        }

        .export-btn {
            background-color: #146C1D;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.2s;
        }

        .export-btn:hover {
            background-color: #1a8a25;
        }

        .settings-panel {
            width: 450px;
            background-color: #1a1a1a;
            border-radius: 8px;
            padding: 15px; /* 调整内边距 */
            margin-left: auto; /* 使设置面板靠右 */
        }

        .section {
            margin-bottom: 15px; /* 调整分区边距 */
        }

        .section-title {
            font-size: 18px;
            margin-bottom: 10px;
            padding-bottom: 5px;
            border-bottom: 1px solid #333;
        }
        
        .toggle-btn {
            width: 100%;
            background-color: #0c4a14;
            color: white;
            border: none;
            padding: 10px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            margin-bottom: 15px; /* 调整边距 */
            transition: background-color 0.2s;
        }
        .toggle-btn:hover {
            background-color: #146C1D;
        }

        .form-group {
            margin-bottom: 10px; /* 调整表单组边距 */
        }

        .image-selectors {
            display: flex;
            flex-direction: column; /* 改为垂直布局 */
            gap: 10px;
        }
        .image-selectors .form-group {
            margin-bottom: 0;
        }

        /* 单选按钮组样式 */
        .radio-group label {
            display: inline-block;
            margin-right: 15px;
            font-size: 14px;
            cursor: pointer;
        }
        .radio-group input[type="radio"] {
            width: auto;
            margin-right: 5px;
            vertical-align: middle;
        }
        #bgUpload {
            margin-top: 5px; /* 上传按钮和单选框的间距 */
        }


        label {
            display: block;
            margin-bottom: 5px;
            font-size: 14px;
        }

        input, textarea, select {
            width: 100%;
            padding: 8px;
            border-radius: 4px;
            border: 1px solid #444;
            background-color: #2a2a2a;
            color: white;
        }
        input[type="file"] {
            padding: 4px;
        }


        textarea {
            height: 120px;
            resize: vertical;
        }

        .coord-inputs, .dimension-inputs, .font-inputs {
            display: flex;
            gap: 10px;
        }

        .coord-inputs .form-group,
        .dimension-inputs .form-group,
        .font-inputs .form-group {
            flex: 1;
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- 左侧预览区域 -->
        <div class="preview-container">
            <div class="preview-area">
                <div class="preview-controls">
                    <button id="prevBtn" class="nav-btn" disabled>上一张</button>
                    <div class="page-indicator" id="pageIndicator">图片 1/1</div>
                    <button id="nextBtn" class="nav-btn" disabled>下一张</button>
                </div>
                <div class="canvas-container">
                    <canvas id="previewCanvas" width="1920" height="1080"></canvas>
                </div>
            </div>
            <button id="exportBtn" class="export-btn">导出所有PNG图片</button>
        </div>

        <!-- 右侧设置面板 -->
        <div class="settings-panel">
            <button id="toggleSettingsBtn" class="toggle-btn">切换至 位置/大小 设置</button>
            
            <div id="textAndImageSettings">
                <!-- 角色与背景 -->
                <div class="section">
                    <h2 class="section-title">主要设置</h2>
                    <div class="form-group">
                        <label for="protagonistName">玩家名</label>
                        <input type="text" id="protagonistName" value="雪泽歌子">
                    </div>
                    <!-- 更新后的图片选择器布局 -->
                    <div class="image-selectors">
                        <div class="form-group">
                            <label>下层背景图片</label>
                            <div class="radio-group">
                                 <input type="radio" name="bgChoice" id="bgChoiceUpload" value="upload" checked>
                                 <label for="bgChoiceUpload">上传图片</label>
                                 <input type="radio" name="bgChoice" id="bgChoiceNone" value="none">
                                 <label for="bgChoiceNone">无</label>
                            </div>
                            <input type="file" id="bgUpload" accept="image/*">
                        </div>
                         <div class="form-group">
                            <label for="dialogueBoxSelect">上层对话框图片</label>
                            <select id="dialogueBoxSelect">
                                <option value="旁白.png" selected>旁白</option>
                                <option value="阿贝拉德.png">阿贝拉德</option>
                                <option value="阿洁塔.png">阿洁塔</option>
                                <option value="伊迪拉.png">伊迪拉</option>
                                <option value="卡西娅.png">卡西娅</option>
                                <option value="海因里希.png">海因里希</option>
                                <option value="婕伊.png">婕伊</option>
                                <option value="帕斯卡.png">帕斯卡</option>
                                <option value="伊莉耶特.png">伊莉耶特</option>
                                <option value="乌尔法.png">乌尔法</option>
                                <option value="玛拉斋.png">玛拉斋</option>
                                <option value="绮贝拉.png">绮贝拉</option>
                                <option value="索罗蒙.png">索罗蒙</option>
                                <option value="upload">-- 上传自定义图片 --</option>
                                <option value="">-- 无 --</option>
                            </select>
                            <input type="file" id="bgUpload2" accept="image/*" style="display: none;">
                        </div>
                    </div>
                </div>

                <!-- 文本输入1 -->
                <div class="section">
                    <h2 class="section-title">文本框1</h2>
                    <div class="form-group">
                        <label for="textInput">在【】内输入角色名，在（）内输入动作。空行以切换下一个图片</label>
                        <textarea id="textInput" placeholder="请输入文本...">【雪泽歌子】:（这是动作）"这是对话。"

【其他角色】:（这是动作）"这是对话。"

（这是旁白旁白旁白旁白旁白）</textarea>
                    </div>
                </div>

                <!-- 文本输入2 -->
                <div class="section">
                    <h2 class="section-title">文本框2</h2>
                    <div class="form-group">
                        <label for="textInput2">换行以增加选项。空行以切换下一个图片</label>
                        <textarea id="textInput2" placeholder="请输入文本...">1.继续
2.“默认文本1。”

1.“默认文本。”
2.“默认文本。”
3.“默认文本。”

1.继续</textarea>
                    </div>
                </div>
            </div>

            <div id="layoutSettings" style="display: none;">
                <!-- 文字框1设置 -->
                <div class="section">
                    <h2 class="section-title">文字框1设置</h2>
                    <div class="coord-inputs">
                        <div class="form-group">
                            <label for="textboxX">X坐标</label>
                            <input type="number" id="textboxX" value="250">
                        </div>
                        <div class="form-group">
                            <label for="textboxY">Y坐标</label>
                            <input type="number" id="textboxY" value="774">
                        </div>
                    </div>
                    <div class="dimension-inputs">
                        <div class="form-group">
                            <label for="textboxWidth">宽度</label>
                            <input type="number" id="textboxWidth" value="740">
                        </div>
                        <div class="form-group">
                            <label for="textboxHeight">高度</label>
                            <input type="number" id="textboxHeight" value="200">
                        </div>
                    </div>
                    <div class="font-inputs">
                         <div class="form-group">
                            <label for="fontSize">字体大小</label>
                            <input type="number" id="fontSize" value="24">
                        </div>
                        <div class="form-group">
                            <label for="lineHeight">行高</label>
                            <input type="number" id="lineHeight" value="33">
                        </div>
                        <div class="form-group">
                            <label for="letterSpacing">字间距</label>
                            <input type="number" id="letterSpacing" value="0">
                        </div>
                    </div>
                </div>

                <!-- 文字框2设置 -->
                <div class="section">
                    <h2 class="section-title">文字框2设置</h2>
                    <div class="coord-inputs">
                        <div class="form-group">
                            <label for="textboxX2">X坐标</label>
                            <input type="number" id="textboxX2" value="1062">
                        </div>
                        <div class="form-group">
                            <label for="textboxY2">Y坐标</label>
                            <input type="number" id="textboxY2" value="755">
                        </div>
                    </div>
                    <div class="dimension-inputs">
                         <div class="form-group">
                            <label for="textboxWidth2">宽度</label>
                            <input type="number" id="textboxWidth2" value="600">
                        </div>
                        <div class="form-group">
                            <label for="textboxHeight2">高度</label>
                            <input type="number" id="textboxHeight2" value="200">
                        </div>
                    </div>
                     <div class="font-inputs">
                        <div class="form-group">
                            <label for="fontSize2">字体大小</label>
                            <input type="number" id="fontSize2" value="24">
                        </div>
                        <div class="form-group">
                            <label for="lineHeight2">行高</label>
                            <input type="number" id="lineHeight2" value="49">
                        </div>
                        <div class="form-group">
                            <label for="letterSpacing2">字间距</label>
                            <input type="number" id="letterSpacing2" value="0">
                        </div>
                    </div>
                </div>

                 <!-- 文字框3设置 -->
                <div class="section">
                    <h2 class="section-title">主角名显示设置 (居中对齐)</h2>
                    <div class="coord-inputs">
                        <div class="form-group">
                            <label for="textboxX3">X坐标 (中心点)</label>
                            <input type="number" id="textboxX3" value="1801">
                        </div>
                        <div class="form-group">
                            <label for="textboxY3">Y坐标</label>
                            <input type="number" id="textboxY3" value="1044">
                        </div>
                    </div>
                    <div class="dimension-inputs">
                         <div class="form-group">
                            <label for="textboxWidth3">宽度</label>
                            <input type="number" id="textboxWidth3" value="300">
                        </div>
                        <div class="form-group">
                            <label for="textboxHeight3">高度</label>
                            <input type="number" id="textboxHeight3" value="200">
                        </div>
                    </div>
                     <div class="font-inputs">
                        <div class="form-group">
                            <label for="fontSize3">字体大小</label>
                            <input type="number" id="fontSize3" value="29">
                        </div>
                        <div class="form-group">
                            <label for="lineHeight3">行高</label>
                            <input type="number" id="lineHeight3" value="38">
                        </div>
                        <div class="form-group">
                            <label for="letterSpacing3">字间距</label>
                            <input type="number" id="letterSpacing3" value="0">
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 获取DOM元素
        const canvas = document.getElementById('previewCanvas');
        const ctx = canvas.getContext('2d');
        const exportBtn = document.getElementById('exportBtn');
        const prevBtn = document.getElementById('prevBtn');
        const nextBtn = document.getElementById('nextBtn');
        const pageIndicator = document.getElementById('pageIndicator');
        
        const toggleSettingsBtn = document.getElementById('toggleSettingsBtn');
        const textAndImageSettings = document.getElementById('textAndImageSettings');
        const layoutSettings = document.getElementById('layoutSettings');

        const protagonistName = document.getElementById('protagonistName');
        
        // 下层背景元素
        const bgUpload = document.getElementById('bgUpload');
        const bgChoiceUpload = document.getElementById('bgChoiceUpload');
        const bgChoiceNone = document.getElementById('bgChoiceNone');
        
        // 上层背景元素
        const dialogueBoxSelect = document.getElementById('dialogueBoxSelect');
        const bgUpload2 = document.getElementById('bgUpload2');


        const textInput = document.getElementById('textInput');
        const textboxX = document.getElementById('textboxX');
        const textboxY = document.getElementById('textboxY');
        const textboxWidth = document.getElementById('textboxWidth');
        const textboxHeight = document.getElementById('textboxHeight');
        const fontSize = document.getElementById('fontSize');
        const lineHeight = document.getElementById('lineHeight');
        const letterSpacing = document.getElementById('letterSpacing');
        
        const textInput2 = document.getElementById('textInput2');
        const textboxX2 = document.getElementById('textboxX2');
        const textboxY2 = document.getElementById('textboxY2');
        const textboxWidth2 = document.getElementById('textboxWidth2');
        const textboxHeight2 = document.getElementById('textboxHeight2');
        const fontSize2 = document.getElementById('fontSize2');
        const lineHeight2 = document.getElementById('lineHeight2');
        const letterSpacing2 = document.getElementById('letterSpacing2');

        const textboxX3 = document.getElementById('textboxX3');
        const textboxY3 = document.getElementById('textboxY3');
        const textboxWidth3 = document.getElementById('textboxWidth3');
        const textboxHeight3 = document.getElementById('textboxHeight3');
        const fontSize3 = document.getElementById('fontSize3');
        const lineHeight3 = document.getElementById('lineHeight3');
        const letterSpacing3 = document.getElementById('letterSpacing3');
        
        const COLORS = {
            textColor: '#000000',
            italicColor: '#5C450A',
            protagonistColor: '#5B0706',
            namedRoleColor: '#146C1D',
            unnamedRoleColor: '#146C1D',
            textBox2Color: '#97c08c',
            textBox3Color: '#625c48'
        };

        const namedRoles = ['阿贝拉德', '阿洁塔', '伊迪拉', '卡西娅', '海因里希', '婕伊', '帕斯卡', '伊莉耶特', '乌尔法', '玛拉斋', '绮贝拉', '索罗蒙'];

        let backgroundImage = null;
        let backgroundImage2 = null;
        let currentPageIndex = 0;
        let textPages1 = [];
        let textPages2 = [];

        function init() {
            const inputsToTrack = [
                protagonistName, textInput, textInput2,
                textboxX, textboxY, textboxWidth, textboxHeight, fontSize, lineHeight, letterSpacing,
                textboxX2, textboxY2, textboxWidth2, textboxHeight2, fontSize2, lineHeight2, letterSpacing2,
                textboxX3, textboxY3, textboxWidth3, textboxHeight3, fontSize3, lineHeight3, letterSpacing3
            ];
            
            inputsToTrack.forEach(input => input.addEventListener('input', renderPreview));

            // 下层背景事件
            bgUpload.addEventListener('change', handleBackgroundUpload);
            bgChoiceUpload.addEventListener('change', handleBgChoiceChange);
            bgChoiceNone.addEventListener('change', handleBgChoiceChange);

            // 上层背景事件
            dialogueBoxSelect.addEventListener('change', handleDialogueBoxChange);
            bgUpload2.addEventListener('change', handleCustomUpperBgUpload);


            exportBtn.addEventListener('click', exportAllImages);
            prevBtn.addEventListener('click', showPreviousPage);
            nextBtn.addEventListener('click', showNextPage);
            
            toggleSettingsBtn.addEventListener('click', () => {
                const isTextSettingsVisible = textAndImageSettings.style.display !== 'none';
                if (isTextSettingsVisible) {
                    textAndImageSettings.style.display = 'none';
                    layoutSettings.style.display = 'block';
                    toggleSettingsBtn.textContent = '切换至 文本/图片 设置';
                } else {
                    textAndImageSettings.style.display = 'block';
                    layoutSettings.style.display = 'none';
                    toggleSettingsBtn.textContent = '切换至 位置/大小 设置';
                }
            });

            // 初始加载默认上层图片
            handleDialogueBoxChange();
            // 初始渲染
            renderPreview();
        }
        
        function splitAndSetPages() {
            textPages1 = textInput.value.split(/\n\s*\n/);
            textPages2 = textInput2.value.split(/\n\s*\n/);
            
            if (textInput.value.trim() === '' && textInput2.value.trim() === '') {
                 textPages1 = [''];
                 textPages2 = [''];
            }
        }

        function updatePageNavigation() {
            const totalPages = Math.max(textPages1.length, textPages2.length);
            pageIndicator.textContent = `图片 ${currentPageIndex + 1}/${totalPages || 1}`;
            prevBtn.disabled = currentPageIndex === 0;
            nextBtn.disabled = currentPageIndex >= (totalPages || 1) - 1;
        }

        function showPreviousPage() {
            if (currentPageIndex > 0) {
                currentPageIndex--;
                renderPreview();
            }
        }

        function showNextPage() {
            const totalPages = Math.max(textPages1.length, textPages2.length);
            if (currentPageIndex < (totalPages || 1) - 1) {
                currentPageIndex++;
                renderPreview();
            }
        }

        // --- 背景图片处理 ---
        function handleBgChoiceChange() {
            if (bgChoiceNone.checked) {
                backgroundImage = null;
                bgUpload.style.display = 'none';
                bgUpload.value = ''; // 清除文件选择，以便下次能重新选择
                renderPreview();
            } else {
                bgUpload.style.display = 'block';
            }
        }

        function handleBackgroundUpload(event) {
            const file = event.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    const img = new Image();
                    img.onload = function() {
                        backgroundImage = img;
                        renderPreview();
                    };
                    img.src = e.target.result;
                };
                reader.readAsDataURL(file);
            }
        }
        
        function handleDialogueBoxChange() {
            const selectedValue = dialogueBoxSelect.value;
            // 如果选择上传，则触发隐藏的input
            if (selectedValue === 'upload') {
                bgUpload2.click();
                return; 
            }
            // 如果选择有效图片名，则加载
            if (selectedValue) {
                const img = new Image();
                img.onload = function() {
                    backgroundImage2 = img;
                    renderPreview();
                };
                img.src = 'images/' + selectedValue;
            } else {
                // 如果选择“无”，则清除
                backgroundImage2 = null;
                renderPreview();
            }
        }
        
        function handleCustomUpperBgUpload(event) {
            const file = event.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    const img = new Image();
                    img.onload = function() {
                        backgroundImage2 = img;
                        renderPreview();
                    };
                    img.src = e.target.result;
                };
                reader.readAsDataURL(file);
            }
        }
        
        // --- 渲染与绘制 ---
        function renderPreview() {
            splitAndSetPages();
            updatePageNavigation();

            ctx.clearRect(0, 0, canvas.width, canvas.height);
            if (backgroundImage) ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
            if (backgroundImage2) ctx.drawImage(backgroundImage2, 0, 0, canvas.width, canvas.height);
            
            drawText1();
            drawText2();
            drawText3();
        }
        
        function drawText1() {
            const text = textPages1[currentPageIndex] || '';
            if (!text.trim()) return;
            
            ctx.textBaseline = 'top';
            ctx.textAlign = 'left';

            const x = parseInt(textboxX.value), y = parseInt(textboxY.value), width = parseInt(textboxWidth.value), height = parseInt(textboxHeight.value);
            const fontSizeValue = parseInt(fontSize.value), lineHeightValue = parseInt(lineHeight.value), letterSpacingValue = parseInt(letterSpacing.value);

            const processedText = processText(text, fontSizeValue);
            const lines = wrapText(processedText, width, letterSpacingValue);
            
            let currentY = y;
            for (const line of lines) {
                if (currentY + lineHeightValue > y + height) break;
                
                let currentX = x;
                for (const segment of line) {
                    ctx.fillStyle = segment.color;
                    ctx.font = segment.style;
                    ctx.fillText(segment.text, currentX, currentY);
                    currentX += ctx.measureText(segment.text).width + (segment.text.length * letterSpacingValue);
                }
                currentY += lineHeightValue;
            }
        }

        function drawText2() {
            const text = textPages2[currentPageIndex] || '';
            if (!text.trim()) return;

            const x = parseInt(textboxX2.value), y = parseInt(textboxY2.value), height = parseInt(textboxHeight2.value);
            const fontSizeValue = parseInt(fontSize2.value), lineHeightValue = parseInt(lineHeight2.value);

            ctx.font = `${fontSizeValue}px SimSun, serif`;
            ctx.textBaseline = 'top';
            ctx.textAlign = 'left';
            ctx.fillStyle = COLORS.textBox2Color;
            
            const lines = text.split('\n');
            let currentY = y;
            for (const line of lines) {
                if (currentY + lineHeightValue > y + height) break;
                ctx.fillText(line, x, currentY);
                currentY += lineHeightValue;
            }
        }

        function drawText3() {
            const text = protagonistName.value.trim();
            if (!text) return;

            const x = parseInt(textboxX3.value), y = parseInt(textboxY3.value), height = parseInt(textboxHeight3.value);
            const fontSizeValue = parseInt(fontSize3.value), lineHeightValue = parseInt(lineHeight3.value);
            
            ctx.font = `${fontSizeValue}px SimSun, serif`;
            ctx.textBaseline = 'top';
            ctx.textAlign = 'center';
            ctx.fillStyle = COLORS.textBox3Color;

            const lines = text.split('\n');
            let currentY = y;
            for (const line of lines) {
                if (currentY + lineHeightValue > y + height) break;
                ctx.fillText(line, x, currentY);
                currentY += lineHeightValue;
            }
        }

        function processText(text, fontSizeValue) {
            const result = [];
            const protName = protagonistName.value.trim();

            const regex = new RegExp(`(【.*?】|（.*?）)`, 'g');
            const parts = text.split(regex).filter(Boolean);

            parts.forEach(part => {
                if (part.startsWith('【') && part.endsWith('】')) {
                    const roleName = part.substring(1, part.length - 1);
                    let roleColor;
                    if (roleName === protName && protName !== '') {
                        roleColor = COLORS.protagonistColor;
                    } else if (namedRoles.includes(roleName)) {
                        roleColor = COLORS.namedRoleColor;
                    } else {
                        roleColor = COLORS.unnamedRoleColor;
                    }
                    result.push({
                        text: roleName,
                        color: roleColor,
                        style: `bold ${fontSizeValue}px SimSun`
                    });
                } 
                else if (part.startsWith('（') && part.endsWith('）')) {
                     result.push({
                        text: part.substring(1, part.length - 1),
                        color: COLORS.italicColor,
                        style: `italic ${fontSizeValue}px SimSun`
                    });
                }
                else {
                    result.push({
                        text: part,
                        color: COLORS.textColor,
                        style: `${fontSizeValue}px SimSun`
                    });
                }
            });
            return result;
        }

        function wrapText(segments, maxWidth, letterSpacing) {
            const lines = [];
            let currentLine = [];
            let currentLineWidth = 0;

            segments.forEach(segment => {
                ctx.font = segment.style;
                const chars = segment.text.split('');
                chars.forEach(char => {
                    const charWidth = ctx.measureText(char).width + letterSpacing;
                    if (currentLineWidth + charWidth > maxWidth && currentLine.length > 0) {
                        lines.push(currentLine);
                        currentLine = [];
                        currentLineWidth = 0;
                    }
                    let lastSegmentInLine = currentLine[currentLine.length - 1];
                    if (lastSegmentInLine && lastSegmentInLine.color === segment.color && lastSegmentInLine.style === segment.style) {
                        lastSegmentInLine.text += char;
                    } else {
                        currentLine.push({ text: char, color: segment.color, style: segment.style });
                    }
                    currentLineWidth += charWidth;
                });
            });
            if (currentLine.length > 0) lines.push(currentLine);
            
            return lines;
        }

        async function exportAllImages() {
            splitAndSetPages();
            const totalPages = Math.max(textPages1.length, textPages2.length);
            
            const exportCanvas = document.createElement('canvas');
            exportCanvas.width = canvas.width;
            exportCanvas.height = canvas.height;
            const exportCtx = exportCanvas.getContext('2d');
            const protName = protagonistName.value.trim();

            for (let i = 0; i < (totalPages || 1); i++) {
                exportCtx.clearRect(0, 0, exportCanvas.width, exportCanvas.height);
                if (backgroundImage) exportCtx.drawImage(backgroundImage, 0, 0, exportCanvas.width, exportCanvas.height);
                if (backgroundImage2) exportCtx.drawImage(backgroundImage2, 0, 0, exportCanvas.width, exportCanvas.height);
                
                drawTextToContext(exportCtx, 1, textPages1[i] || '');
                drawTextToContext(exportCtx, 2, textPages2[i] || '');
                drawTextToContext(exportCtx, 3, protName);

                const link = document.createElement('a');
                link.download = `generated-image-${i + 1}.png`;
                link.href = exportCanvas.toDataURL('image/png');
                link.click();
                await new Promise(r => setTimeout(r, 100));
            }
        }

        function drawTextToContext(context, boxNumber, text) {
            if (boxNumber !== 3 && !text.trim()) return;
            if (boxNumber === 3 && !text) return;

            switch (boxNumber) {
                case 1: {
                    context.textBaseline = 'top'; context.textAlign = 'left';
                    const x = parseInt(textboxX.value), y = parseInt(textboxY.value), width = parseInt(textboxWidth.value), height = parseInt(textboxHeight.value);
                    const fontSizeValue = parseInt(fontSize.value), lineHeightValue = parseInt(lineHeight.value), letterSpacingValue = parseInt(letterSpacing.value);
                    const processedText = processText(text, fontSizeValue);
                    const lines = wrapText(processedText, width, letterSpacingValue);
                    let currentY = y;
                    for (const line of lines) {
                        if (currentY + lineHeightValue > y + height) break;
                        let currentX = x;
                        for (const segment of line) {
                            context.fillStyle = segment.color;
                            context.font = segment.style;
                            context.fillText(segment.text, currentX, currentY);
                            currentX += context.measureText(segment.text).width + (segment.text.length * letterSpacingValue);
                        }
                        currentY += lineHeightValue;
                    }
                    break;
                }
                case 2: {
                    const x = parseInt(textboxX2.value), y = parseInt(textboxY2.value), height = parseInt(textboxHeight2.value);
                    const fontSizeValue = parseInt(fontSize2.value), lineHeightValue = parseInt(lineHeight2.value);
                    context.font = `${fontSizeValue}px SimSun, serif`;
                    context.textBaseline = 'top'; context.textAlign = 'left'; context.fillStyle = COLORS.textBox2Color;
                    const lines = text.split('\n');
                    let currentY = y;
                    for (const line of lines) {
                        if (currentY + lineHeightValue > y + height) break;
                        context.fillText(line, x, currentY);
                        currentY += lineHeightValue;
                    }
                    break;
                }
                case 3: {
                    const x = parseInt(textboxX3.value), y = parseInt(textboxY3.value), height = parseInt(textboxHeight3.value);
                    const fontSizeValue = parseInt(fontSize3.value), lineHeightValue = parseInt(lineHeight3.value);
                    context.font = `${fontSizeValue}px SimSun, serif`;
                    context.textBaseline = 'top'; context.textAlign = 'center'; context.fillStyle = COLORS.textBox3Color;
                    const lines = text.split('\n');
                    let currentY = y;
                    for (const line of lines) {
                        if (currentY + lineHeightValue > y + height) break;
                        context.fillText(line, x, currentY);
                        currentY += lineHeightValue;
                    }
                    break;
                }
            }
        }

        window.onload = init;
    </script>
</body>
</html>```